﻿/*
 * 由SharpDevelop创建。
 * 用户： Administrator
 * 日期: 2017/7/7
 * 时间: 23:26
 * 
 * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
 */
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;

namespace TIDTool
{
	/// <summary>
	/// TidFileWriter类<br/>
	/// 用于输出tid文件
	/// </summary>
	public class TidFileWriter
	{
		public string fileName;
		public TidFile tidFile;
		
		public TidFileWriter(string filename, TidFile tidfile)
		{
			fileName = filename;
			tidFile = tidfile;
		}
		
		public void WriteAll()
		{
			FileStream stream = new FileStream(fileName, FileMode.OpenOrCreate);
			BinaryWriter bw = new BinaryWriter(stream);
			
			// 1. 生成文件头
			byte[] headerBytes = new byte[256];
			Array.Clear(headerBytes, 0, headerBytes.Length);
			
			// 1.1 标题文本
			byte[] headerTextBytes = Encoding.UTF8.GetBytes(TidFile.HeaderText);
			Array.Copy(headerTextBytes, headerBytes, headerTextBytes.Length);
			
			// 1.2 起始文件号
			ByteUtils.BytesSet(headerBytes, 0x7C, tidFile.BeginNumber, true);
			
			// 1.3 公共文件信息区偏移
			int privateInfoIndexLength = 4 + 4 + 7 * tidFile.PrivateInfoIndex.Count;
			int privateInfoLength = 8 * tidFile.PrivateFileList.Count;
			int privateDataLength = 0;
			foreach (KeyValuePair<TidPosition, byte[]> pair in tidFile.PrivateFileList)
			{
				privateDataLength += pair.Key.fileLength;
			}
			int publicDataLength = 0;
			foreach (KeyValuePair<TidPosition, byte[]> pair in tidFile.PublicFileList)
			{
				publicDataLength += pair.Key.fileLength;
			}
			int publicInfoOffset = 0x100 + 0x10 + 
				privateInfoIndexLength + privateDataLength + privateInfoLength + 
				0x60000 + publicDataLength;
			ByteUtils.BytesSet(headerBytes, 0x84, publicInfoOffset, false);
			
			bw.Write(headerBytes);
			
			// 2. 固定分隔符
			byte[] FixStrBytes = Encoding.UTF8.GetBytes(TidFile.FixStr);
			bw.Write(FixStrBytes);
			
			int curPos = 0;
			int curOffset = 0;
			
			// 3. 私有音频信息索引区
			byte[] privateInfoIndexBytes = new byte[privateInfoIndexLength];
			int privateBeginFileNumber = 0;
			curPos = 8;
			curOffset = 0x100 + 0x10 + privateInfoIndexLength + privateDataLength;
			foreach (TidPosition pos in tidFile.PrivateInfoIndex)
			{
				if (privateBeginFileNumber == 0)
					privateBeginFileNumber = pos.fileNumber;
				if (pos.beginOffset >= 0)
				{
					ByteUtils.BytesSet(privateInfoIndexBytes, curPos, TidFile.FixNumber, true);
					ByteUtils.BytesSet(privateInfoIndexBytes, curPos + 3, curOffset, false);
					curOffset += 8;
				}
				else
				{
					ByteUtils.BytesSet(privateInfoIndexBytes, curPos, 0xFFFFFFFF, true);
					ByteUtils.BytesSet(privateInfoIndexBytes, curPos + 3, 0xFFFFFFFF, false);
				}
				curPos += 7;
			}
			ByteUtils.BytesSet(privateInfoIndexBytes, 0, tidFile.PrivateInfoIndex.Count, true);
			ByteUtils.BytesSet(privateInfoIndexBytes, 4, privateBeginFileNumber, true);
			bw.Write(privateInfoIndexBytes);
			
			// 4. 私有音频数据区
			foreach (KeyValuePair<TidPosition, byte[]> pair in tidFile.PrivateFileList)
			{
				bw.Write(pair.Value);
			}
			
			// 5. 私有音频信息区
			byte[] privateInfoBytes = new byte[privateInfoLength];
			curPos = 0;
			curOffset = 0x100 + 0x10 + privateInfoIndexLength;
			foreach (KeyValuePair<TidPosition, byte[]> pair in tidFile.PrivateFileList)
			{
				ByteUtils.BytesSet(privateInfoBytes, curPos, curOffset, false);
				ByteUtils.BytesSet(privateInfoBytes, curPos + 4, pair.Key.fileLength, false);
				curOffset += pair.Key.fileLength;
				curPos += 8;
			}
			bw.Write(privateInfoBytes);
			
			// 6. 固定分隔符
			byte[] fixBytes = new byte[0x60000];
			for (int i = 0; i < fixBytes.Length; i++)
			{
				fixBytes[i] = (byte)0xFF;
			}
			bw.Write(fixBytes);
			
			// 7. 公共音频数据区
			foreach (KeyValuePair<TidPosition, byte[]> pair in tidFile.PublicFileList)
			{
				bw.Write(pair.Value);
			}
			
			// 8. 公共音频信息区
			int publicInfoLength = 8 * tidFile.PublicInfoIndex.Count;
			byte[] publicInfoBytes = new byte[publicInfoLength];
			curPos = 0;
			curOffset = 0x100 + 0x10 + 
				privateInfoIndexLength + privateDataLength + privateInfoLength +
				0x60000;
			foreach (TidPosition pos in tidFile.PublicInfoIndex)
			{
				if (pos.beginOffset >= 0)
				{
					ByteUtils.BytesSet(publicInfoBytes, curPos, curOffset, false);
					ByteUtils.BytesSet(publicInfoBytes, curPos + 4, pos.fileLength, false);
					curOffset += pos.fileLength;
				}
				else
				{
					ByteUtils.BytesSet(publicInfoBytes, curPos, 0xFFFFFFFF, false);
					ByteUtils.BytesSet(publicInfoBytes, curPos + 4, 0xFFFFFFFF, false);
				}
				curPos += 8;
			}
			bw.Write(publicInfoBytes);
			
			bw.Close();
		}
	}
}
